﻿#region COPYRIGHT© 2005-2013 Phillip Clark. All rights reserved.

// For licensing information see License.txt (MIT style licensing).

#endregion

namespace FlitBit.Parse
{
	/// <summary>
	/// Character match rule that matches an exact sequence of rules given to the constructor.
	/// </summary>
	public class CharRuleExact : CharRule
	{
		internal CharRuleExact(params CharMatch[] parts)
			: base(MatchKind.Exact, parts)
		{}

		/// <summary>
		///   Determines if the cursor position within the input is at a matching sequence.
		/// </summary>
		/// <param name="input">the input</param>
		/// <param name="cursor">the cursor</param>
		/// <returns>
		///   <em>true</em> if positioned at a matching sequence; otherwise <em>false</em>.
		/// </returns>
		public override bool At(char[] input, Cursor cursor)
		{
			if (input == null || cursor >= input.Length)
			{
				return false;
			}
			var c = cursor;
			foreach (var m in this._rules)
			{
				if (!m.TryAt(input, ref c))
				{
					return false;
				}
			}
			return true;
		}

		/// <summary>
		///   Determines if the cursor position within the input is at a matching sequence.
		/// </summary>
		/// <param name="input">the input</param>
		/// <param name="cursor">the cursor</param>
		/// <returns>
		///   <em>true</em> if positioned at a matching sequence; otherwise <em>false</em>.
		/// </returns>
		public override bool At(string input, Cursor cursor)
		{
			if (input == null || cursor >= input.Length)
			{
				return false;
			}
			var c = cursor;
			foreach (var m in this._rules)
			{
				if (!m.TryAt(input, ref c))
				{
					return false;
				}
			}
			return true;
		}

		/// <summary>
		///   Determines if the instance is equal to another.
		/// </summary>
		/// <param name="obj">the other object</param>
		/// <returns><em>true</em> if equal; otherwise <em>false</em>.</returns>
		public override bool Equals(object obj)
		{
			return obj is CharRuleExact
				&& this.Equals((CharRuleExact) obj);
		}

		/// <summary>
		///   Gets the object's hashcode.
		/// </summary>
		/// <returns></returns>
		public override int GetHashCode()
		{
			return base.GetHashCode();
		}

		/// <summary>
		///   Tries to match the sequence at the cursor position, advancing the cursor if successful.
		/// </summary>
		/// <param name="input">the input</param>
		/// <param name="cursor">a reference to the cursor</param>
		/// <returns>
		///   <em>true</em> if the sequence matched at the initial cursor; otherwise <em>false</em>.
		/// </returns>
		public override bool TryAt(char[] input, ref Cursor cursor)
		{
			if (input == null || cursor >= input.Length)
			{
				return false;
			}
			var c = cursor;
			foreach (var m in this._rules)
			{
				if (!m.TryAt(input, ref c))
				{
					return false;
				}
			}
			cursor = c;
			return true;
		}

		/// <summary>
		///   Tries to match the sequence at the cursor position, advancing the cursor if successful.
		/// </summary>
		/// <param name="input">the input</param>
		/// <param name="cursor">a reference to the cursor</param>
		/// <returns>
		///   <em>true</em> if the sequence matched at the initial cursor; otherwise <em>false</em>.
		/// </returns>
		public override bool TryAt(string input, ref Cursor cursor)
		{
			if (input == null || cursor >= input.Length)
			{
				return false;
			}
			var c = cursor;
			foreach (var m in this._rules)
			{
				if (!m.TryAt(input, ref c))
				{
					return false;
				}
			}
			cursor = c;
			return true;
		}

		/// <summary>
		/// Determines if an instance is equal to another.
		/// </summary>
		/// <param name="other">the other</param>
		/// <returns><em>true</em> if equal; otherwise <em>false</em>.</returns>
		public bool Equals(CharRuleExact other)
		{
			return Equals((CharRule) other);
		}
	}
}